package lru;

import Atop100.listNode.LRUcacheDemo;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Lru0829 {

    class Node<K, V> {
        K key;
        V value;
        //TODO:2023/8/29 写的不对的地方
        Node<K, V> pre;
        Node<K, V> next;
        //TODO:2023/8/29  没写
        public Node() {
            this.pre = this.next = null;
        }

        //TODO:2023/8/29  没写  泛型的本质是参数化类型，
        // 即给类型指定一个参数，然后在使用时再指定此参数具体的值，
        // 那样这个类型就可以在使用时决定了。
        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.pre = this.next = null;
        }
    }

    //TODO:2023/8/29 泛型类
    class DoubleLinkedList<K, V> {
        //TODO:2023/8/29
        Node<K, V> head;
        Node<K, V> tail;

        //TODO:2023/8/29 加上public
        public DoubleLinkedList() {
            //TODO:2023/8/29 加上<>
            head = new Node<>();
            tail = new Node<>();
//TODO:2023/8/29 为双向链表 要与单向循环链表区分开
            head.next = tail;
//              head.pre=tail;
//              tail.next=head;
            tail.pre = head;
        }

        public void addHead(Node<K, V> node) {
            node.next = head.next;
            node.pre = head;
            //TODO:2023/8/29 少了
            head.next.pre = node;
            head.next = node;
        }


        public void removeNode(Node<K, V> node) {
            node.next.pre = node.pre;
            node.pre.next = node.next;
            //TODO:2023/8/29 这里很容易忽略
            node.pre = null;
            node.next = null;

        }

        public Node getLast() {
            return tail.pre;
        }


    }

    //TODO:2023/8/29 map这样定义应该不对
    private int capacity;
    //    HashMap map;
//    DoubleLinkedList  doubleLinkedList;
    //TODO:2023/8/29 主要看这里如何定义使用
    Map<Integer, Node<Integer, Integer>> map;
    DoubleLinkedList<Integer, Integer> doubleLinkedList;

    Lru0829(int capacity) {
        this.map = new HashMap<>();
        this.capacity = capacity;
        this.doubleLinkedList = new DoubleLinkedList<>();
    }

    //TODO:2023/8/29  方法的访问控制符如何控制
//    public   int  get(Node  node){
    public int get(int key) {
        if (!map.containsKey(key)) {
            return -1;
        }
        Node<Integer, Integer> node = map.get(key);
//            Node o = (Node)map.get(node.key);
        doubleLinkedList.removeNode(node);
        doubleLinkedList.addHead(node);
        return node.value;
    }

    //TODO:2023/8/29 然后就是泛型的操作和使用
    public void put(int key, int value) {
        //TODO:2023/8/29 这里map如何存储 存的是什么
        if (map.containsKey(key)) {
            Node<Integer, Integer> node = map.get(key);
            node.value = value;
            map.put(key, node);
            doubleLinkedList.removeNode(node);
            doubleLinkedList.addHead(node);
        } else {

            if (map.size() == capacity) {

                Node<Integer,Integer> last = doubleLinkedList.getLast();
                map.remove(last.key);

                doubleLinkedList.removeNode(last);

            }
                Node<Integer, Integer> newNode = new Node<>(key, value);
                map.put(key, newNode);
                doubleLinkedList.addHead(newNode);

        }


    }

    public static void main(String[] args) {

        Lru0829 lruCacheDemo = new Lru0829(3);


        lruCacheDemo.put(1, 1);
        lruCacheDemo.put(2, 2);
        lruCacheDemo.put(3, 3);

//        for (:
//             lruCacheDemo.doubleLinkedList) {
//
//        }

//        System.out.println(lruCacheDemo.map.keySet());

        lruCacheDemo.put(4, 1);
        System.out.println(lruCacheDemo.map.keySet());
//        lruCacheDemo.put(3, 1);
//        System.out.println(lruCacheDemo.map.keySet());
//        lruCacheDemo.put(3, 1);
//        System.out.println(lruCacheDemo.map.keySet());
//        lruCacheDemo.put(3, 1);
//        System.out.println(lruCacheDemo.map.keySet());
//        lruCacheDemo.put(5, 1);
//        System.out.println(lruCacheDemo.map.keySet());



//        Set<Map.Entry<Integer, Node<Integer, Integer>>> entries =lruCacheDemo.map.entrySet();
//        Iterator<Map.Entry<Integer,Node<Integer, Integer>>> iterator = entries.iterator();
//        while (iterator.hasNext()){
//            Map.Entry<Integer, Node<Integer, Integer>> next = iterator.next();
//            System.out.println(next.getKey()+"  "+next.getValue().value);
//        }
    }


}